"""
    @File        : classics_fight.py
    @Author      : 狡猾的皮球
    @Date        : 2020/7/9 21:20
    @QQ          : 871245007
    @Description :
        经典回合制战斗系统，类似于梦幻西游的战斗系统
        战斗单位属性：
            基本属性：
                等级：最低0级，最高200级
                气血：气血分为当前气血和气血上限
                魔法：魔法分为当前魔法和魔法上限
                法防：法术防御力
                伤害：物理攻击力
                防御：物理防御力
                速度：出手速度
                灵力：法术攻击力
                暴击：出现暴击的几率，只有装备或者buff才能增加暴击率，初始暴击率为5%
            修炼属性：
                攻击修炼：提升物理伤害 level*2%+10*level
                法术修炼：提升法术伤害 level*2%+5*level
                防御修炼：减少物理伤害 level*2%+5*level
                法防修炼：减少法术伤害 level*2%+5*level
            技能属性（类型）：
                单体物理攻击
                群体物理攻击
                单体法术攻击
                群体法术攻击
                单体恢复（加血或者加蓝）
                群体恢复（加血或者加蓝）
                单体增益（增加攻击力、防御力、暴击率等等）
                群体增益（增加攻击力、防御力、暴击率等等）
                单体减益（降低攻击力、防御力、暴击率，封印、睡眠、中毒敌人）
                群体减益（降低攻击力、防御力、暴击率，封印、睡眠、中毒敌人）
                被动技能（增加攻击力、防御力、暴击率、攻击带毒、攻击连击、法术连击等等）

        战斗系统运行流程：
            1.初始化战斗双方战斗对象
            2.初始化战斗脚本数据（可能会在指定回合触发剧情等等）
            3.玩家给我方人员下达操作指令（攻击、法术、道具）
            4.敌人自动下达操作指令（特殊战斗可能按照战斗脚本数据下达指令，一般战斗由AI做出决策）
            5.检测回合开始时是否触发脚本
            6.计算本回合的战斗结果，产出本回合的战斗数据，例如:
                [
                    {"source":"李逍遥","cmd":"普通攻击","target":"千叶禅师","damage":500,"是否暴击":"是"},
                    {"source":"千叶禅师","cmd":"普通攻击","target":"李逍遥","damage":100,"是否暴击":"否"},
                    {"source":"李忆如","cmd":"道具","target":"李逍遥","item":"金创药","damage":300},
                ]
            7.根据计算的战斗结果播放战斗动画
            8.检测回合结束时是否触发脚本
            9.是否战斗结束？
                *是，结束战斗，结算奖励
                *否，重复3、4、5、6、7、8、9步骤

        其他：
            最多支持5vs5的战斗

        开发进度：
            * 场景，已完成
            * 人物状态控制，已完成
            * 人物高亮，已完成
            * 鼠标选择人物之后高亮，已完成
            * 操作菜单
            * 显示人物气血和魔法值
"""
import json
import math
import os
import random
from typing import List

import pygame
from pygame.mask import Mask
from pygame import Surface

from code.engine.animation import Animation
from code.engine.gui import ButtonEx
from code.engine.sprite import Sprite, draw_src_text
from code.game_global import g


class FighterResourceManager:
    """
    战斗者资源管理器
    整个游戏中，只需要实例化一次本类
    可以把本类存在g对象中
    """

    def __init__(self):
        # 缓存（以fighter_name为键）
        self.cache = dict()

    def load(self, fighter_name):
        """
        加载战斗素材
        """
        # 如果有缓存，先使用缓存中的
        if fighter_name in self.cache:
            return self.cache.get(fighter_name)
        file_dir_path = f"./resource/Battlers/{fighter_name}/"
        data = {
            "idle": self.__load_action(file_dir_path, "待机"),
            "be_attacked": self.__load_action(file_dir_path, "挨打"),
            "attack": self.__load_action(file_dir_path, "攻击"),
            "magic": self.__load_action(file_dir_path, "施法"),
            "dead_ing": self.__load_action(file_dir_path, "死亡"),
            "def": self.__load_action(file_dir_path, "防御"),
        }
        self.cache[fighter_name] = data
        return data

    def __load_action(self, file_dir_path, action_name):
        """
        加载对应action的素材,返回surface和对应的mask
        """
        final_path = file_dir_path + action_name + "/"
        actor_path = final_path + "actor/"
        enemy_path = final_path + "enemy/"
        actor_files = self.__get_action_files(actor_path)
        enemy_files = self.__get_action_files(enemy_path)
        actor_surfaces = g.res_mgr.get_surface_list(actor_files)
        enemy_surfaces = g.res_mgr.get_surface_list(enemy_files)
        return {
            "actor_surfaces": actor_surfaces,
            "actor_masks": [pygame.mask.from_surface(surf) for surf in actor_surfaces],
            "enemy_surfaces": enemy_surfaces,
            "enemy_masks": [pygame.mask.from_surface(surf) for surf in enemy_surfaces]
        }

    @staticmethod
    def __get_action_files(dir_path):
        """
        获取对应action所有的文件路径，最大不超过100个文件
        """
        file_path_list = []
        for i in range(99):
            num_len = len(str(i))
            file_name = "0" * (2 - num_len) + str(i) + ".png"
            file_path = dir_path + file_name
            if not os.path.exists(file_path):
                break
            file_path_list.append(file_path)
        return file_path_list


class FighterAnimation:
    """
    战斗者动画类
    """

    def __init__(self, frame_list: List[Surface], mask_list: List[Mask], time, frame_callback=None, done_callback=None):
        """
        :param time:动画播放时长,单位毫秒
        :param frame_callback:帧回调
        :param done_callback:完成回调
        """
        self.img_light = None
        self.sw_light = False  # 是否开启高亮
        self.time = time
        self.frame_list = frame_list
        # 一共多少帧
        self.frame = len(frame_list)
        self.frame_range = [0, self.frame - 1]
        self.dw = self.frame_list[0].get_width()
        self.dh = self.frame_list[0].get_height()
        self.speed = int(time / self.frame)
        self.least_once = False  # 动画是否至少播放了一次
        self.frame_callback = frame_callback
        self.done_callback = done_callback
        # 精灵图的行和列
        self.row = 1
        self.col = self.frame
        self.current_frame = self.frame_range[0]  # 当前帧
        self.frame_count = int(self.speed / (1000 / g.fps))  # 需要等待几次主循环才切换1帧
        self.current_count = self.frame_range[0] * self.frame_count  # 当前计数
        # 碰撞遮罩
        self.mask_list = mask_list
        self.pause = False  # 是否暂停
        if self.frame_count < 1:
            self.frame_count = 1

    def update(self):
        if self.pause:
            return
        last_frame = self.current_frame
        self.current_count += 1
        self.current_frame = int(self.current_count / self.frame_count)
        if self.current_frame > self.frame_range[1]:
            # 播放完成
            self.current_frame = self.frame_range[0]
            self.current_count = self.frame_range[0] * self.frame_count
            self.least_once = True
            # 帧回调
            if self.frame_callback:
                self.frame_callback(last_frame)
            # 完成回调
            if self.done_callback:
                self.done_callback(last_frame)
        else:
            # 播放中
            # 每个动画帧回调，而不是每个主循环回调
            if last_frame != self.current_frame and self.frame_callback:
                self.frame_callback(last_frame)

    def draw(self, surface, x, y):
        """
        绘图，把x，y作为左上角绘制
        """
        Sprite.blit(surface, self.frame_list[self.current_frame], x, y)

    def reset(self):
        """
        重置动画
        """
        self.current_frame = 0
        self.current_count = 0
        self.least_once = False
        self.pause = False

    def collide(self, x, y) -> bool:
        """
        碰撞检测
        x,y:以mask左上角为原点的坐标
        返回值：True碰撞了 False没碰撞
        """
        if not (0 <= x < self.dw and 0 <= y < self.dh):
            return False
        return bool(self.mask_list[self.current_frame].get_at(x, y))


class FighterRenderer:
    """
    战斗者渲染器，用于控制战斗者的显示、动画状态转换等
    """
    STEP = 1  # 移动的时候，每一帧移动的距离（像素）
    ENUM_IDLE = 0  # 闲置
    ENUM_ATK = 1  # 攻击
    ENUM_BE_ATK = 2  # 挨打
    ENUM_MAGIC = 3  # 施法
    ENUM_DEAD_ING = 4  # 死亡中
    ENUM_DEAD = 5  # 死亡躺下
    ENUM_MOVING = 6  # 移动中

    def __init__(self, x, y, is_actor, res_list: list):
        # 战斗管理器引用
        self.fight_mgr = None
        # 是否为友军
        self.is_actor = is_actor
        # 以下所有坐标均为战斗者脚底绘图坐标坐标
        self.dw = None
        self.dh = None
        # 相关动画
        self.ani_idle = []  # 闲置动画
        self.ani_attack = []  # 攻击动画
        self.ani_magic = []  # 施法动画
        # 加载资源
        self.load(res_list)
        # 初始位置坐标
        self.raw_x = x
        self.raw_y = y
        # 实时位置的坐标
        self.x = self.raw_x
        self.y = self.raw_y
        # 起点坐标
        self.x0 = 0
        self.y0 = 0
        # 终点坐标
        self.xt = None
        self.yt = None
        self.n = 0  # 位移进度[0,1]
        self.k = 0  # 位移比例（每帧的位移比例）
        # 人物初始状态
        self.state = self.ENUM_IDLE
        # 脚底阴影
        self.shadow = g.res_mgr.get_surface("./resource/Battlers/shadow.png")

    def load(self, res_list):
        """
        分配资源
        """
        team_str = "actor" if self.is_actor else "enemy"
        self.dw = res_list[0]["idle"][f"{team_str}_surfaces"][0].get_width()
        self.dh = res_list[0]["idle"][f"{team_str}_surfaces"][0].get_height()

        for index, res in enumerate(res_list):
            self.ani_idle.append(
                FighterAnimation(
                    res["idle"][f"{team_str}_surfaces"],
                    res["idle"][f"{team_str}_masks"],
                    800
                )
            )
            self.ani_attack.append(
                FighterAnimation(
                    res["attack"][f"{team_str}_surfaces"],
                    res["attack"][f"{team_str}_masks"],
                    800,
                    done_callback=self.attack_done if index == 0 else None
                )
            )
            self.ani_magic.append(
                FighterAnimation(
                    res["magic"][f"{team_str}_surfaces"],
                    res["magic"][f"{team_str}_masks"],
                    800
                )
            )

    def get_xy(self, x, y):
        """
        获取用于画图的xy
        """
        foot_x = x - self.dw / 2
        foot_y = y - self.dh
        return foot_x, foot_y

    def moving(self):
        """
        移动逻辑
        """
        if self.state != self.ENUM_MOVING:
            return
        self.n += self.k
        if self.n >= 1:
            self.n = 1
            self.change_state(self.ENUM_IDLE)
        self.x = self.n * (self.xt - self.x0) + self.x0
        self.y = self.n * (self.yt - self.y0) + self.y0

    def move(self, x, y):
        """
        移动
        """
        self.x0 = self.x
        self.y0 = self.y
        self.xt = x
        self.yt = y
        self.n = 0
        # TODO:这里需要改成按距离比例移动而不是时间
        self.k = 1 / g.fps  # 1秒移动过去
        self.change_state(self.ENUM_MOVING)

    def attack(self):
        self.change_state(self.ENUM_ATK)

    def attack_done(self, frame):
        self.change_state(self.ENUM_IDLE)

    def logic(self):
        if self.state == self.ENUM_IDLE:
            for ani_idle in self.ani_idle:
                ani_idle.update()
        elif self.state == self.ENUM_MOVING:
            for ani_idle in self.ani_idle:
                ani_idle.update()
            self.moving()
        elif self.state == self.ENUM_ATK:
            for ani_atk in self.ani_attack:
                ani_atk.update()

    def render(self, target):
        """
        渲染战斗者
        """
        x, y = self.get_xy(self.x, self.y)
        # 绘制脚底阴影
        Sprite.blit_center(target, self.shadow, self.x, self.y - 10)
        if self.state == self.ENUM_IDLE:
            for ani_idle in self.ani_idle:
                ani_idle.draw(target, x, y)
        elif self.state == self.ENUM_MOVING:
            for ani_idle in self.ani_idle:
                ani_idle.draw(target, x, y)
        elif self.state == self.ENUM_ATK:
            for ani_atk in self.ani_attack:
                ani_atk.draw(target, x, y)
        # DEBUG定位
        # Sprite.draw_fill_rect(target, self.foot_x-2, self.foot_y-2, 4, 4, (255, 0, 0))
        # Sprite.draw_fill_rect(target, self.x-2, self.y-2, 4, 4, (0, 255, 0))

    def change_state(self, target_state):
        """
        改变状态
        """
        state_ani_map = {
            self.ENUM_IDLE: self.ani_idle,
            self.ENUM_MOVING: self.ani_idle,
            self.ENUM_MAGIC: self.ani_magic,
            self.ENUM_ATK: self.ani_attack,
        }
        ani_list = state_ani_map[self.state]
        for ani in ani_list:
            ani.reset()
        print("-----------------------------")
        print("改变前:", self.state)
        self.state = target_state
        print("改变后:", self.state)


class Fighter:
    """
    战斗者类
    """
    STEP = 1  # 移动的时候，每一帧移动的距离（像素）
    ENUM_IDLE = 0  # 闲置状态
    ENUM_ATK = 1  # 攻击状态
    ENUM_BE_ATK = 2  # 被攻击状态
    ENUM_MAGIC = 3  # 施法状态
    ENUM_DEAD = 4  # 死亡状态
    ENUM_MOVE = 5  # 移动状态

    def __init__(self, **kwargs):
        # 战斗管理器引用
        self.fight_mgr = None
        # 战斗基本属性
        self.level = kwargs["level"]  # 等级
        self.hp = kwargs["hp"]  # 生命值
        self.mp = kwargs["mp"]  # 魔法值
        self.magic_def = kwargs["magic_def"]  # 法术防御力
        self.atk = kwargs["atk"]  # 伤害（物理攻击力）
        self.defense = kwargs["defense"]  # 防御力
        self.agi = kwargs["agi"]  # 速度
        self.magic = kwargs["magic"]  # 灵力
        self.cri = kwargs["cri"]  # 暴击率，单位%
        # 修炼属性
        self.atk_practice = kwargs["atk_practice"]  # 攻击修炼
        self.magic_practice = kwargs["magic_practice"]  # 法术修炼
        self.def_practice = kwargs["def_practice"]  # 防御修炼
        self.magic_def_practice = kwargs["magic_def_practice"]  # 法防修炼
        # 其他属性
        self.name = kwargs["name"]  # 姓名
        self.is_enemy = kwargs["is_enemy"]  # 是否为敌人
        self.position = kwargs["position"]  # 几号位
        # 渲染属性
        self.id = kwargs["id"]
        # 以下坐标都是中心点坐标
        # 初始位置坐标
        self.raw_x = None
        self.raw_y = None
        # 实时位置的坐标
        self.x = None
        self.y = None
        # 起点坐标
        self.x0 = 0
        self.y0 = 0
        # 终点坐标
        self.xt = None
        self.yt = None
        self.n = 0  # 位移进度[0,1]
        self.k = 0  # 位移比例（每帧的位移比例）
        self.moving = False  # 位移开关
        self.ani_idle = None  # 闲置动画
        self.ani_attack = None  # 攻击动画
        self.ani_be_attacked = None  # 被攻击动画
        self.ani_magic = None  # 施法动画
        self.ani_move = None  # 移动前进动画
        self.ani_back = None  # 移动后退动画
        # 人物动画状态
        self.state = Fighter.ENUM_IDLE  # 0闲置状态 1攻击状态 2被攻击状态 3施法状态 4死亡状态
        self.attack_target = None  # 普通攻击目标

        self.load()

    def load(self):
        """
        加载资源
        """
        # 加载配置文件
        with open(f'./resource/PicLib/fighter/{self.id}/attack.json', 'r', encoding='utf8') as file:
            cfg = json.load(file)
        # 创建闲置动画
        dw = cfg['idle_ani']['cell_w']
        dh = cfg['idle_ani']['cell_h']
        time = cfg['idle_ani']['time']
        frame_range = cfg['idle_ani']['frame_range']
        img_idle, img_idle_light = g.res_mgr.get_two_surface(f"./resource/PicLib/fighter/{self.id}/idle.png")
        self.ani_idle = Animation(self.x, self.y, img_idle, dw, dh, time, True, frame_range, fps=g.fps)
        self.ani_idle.img_light = img_idle_light
        # 创建攻击动画
        dw = cfg['attack_ani']['cell_w']
        dh = cfg['attack_ani']['cell_h']
        time = cfg['attack_ani']['time']
        frame_range = cfg['attack_ani']['frame_range']
        sound_frame = cfg['attack_ani']['sound_frame']
        extra_frame = cfg['attack_ani']['extra_frame']
        attack_frame = cfg['attack_ani']['attack_frame']
        move_frame = cfg['attack_ani']['move_frame']
        img_atk = g.res_mgr.get_surface(f"./resource/PicLib/fighter/{self.id}/attack.png")
        frame_count = int(time / (frame_range[1] - frame_range[0] + 1) / (1000 / g.fps))
        self.ani_attack_frame_count = frame_count
        self.move_frame = move_frame
        self.ani_attack = Animation(
            self.x,
            self.y,
            img_atk,
            dw,
            dh,
            time,
            False,
            frame_range,
            fps=g.fps,
            frame_callback=self.attack_cb(sound_frame, attack_frame, extra_frame, move_frame, frame_count),
            done_callback=None
        )
        if not move_frame:
            self.ani_move = None
        else:
            self.ani_move = Animation(
                self.x,
                self.y,
                img_atk,
                dw,
                dh,
                time,
                False,
                move_frame[0],
                fps=g.fps,
                frame_callback=self.move_cb(move_frame[0]),
                done_callback=None
            )
        # 创建被攻击动画
        dw = cfg['be_attacked_ani']['cell_w']
        dh = cfg['be_attacked_ani']['cell_h']
        time = cfg['be_attacked_ani']['time']
        frame_range = cfg['be_attacked_ani']['frame_range']
        img_be_atk = g.res_mgr.get_surface(f"./resource/PicLib/fighter/{self.id}/be_attacked.png")
        self.ani_be_attacked = Animation(
            self.x,
            self.y,
            img_be_atk,
            dw,
            dh,
            time,
            False,
            frame_range,
            fps=g.fps
        )

    def attack_cb(self, sound_frame, attack_frame, extra_frame, move_frame, frame_count):
        """
        攻击回调
        """

        def cb(frame):
            for sf in sound_frame:
                if sf[1] == frame:
                    # 播放音效
                    g.audio_player.play_sound(sf[0])
                    break
            # if frame == attack_frame[0]:
            #     # 敌人改为受击状态
            #     self.attack_target.state = Fighter.ENUM_BE_ATK
            #
            # elif frame == attack_frame[1]:
            #     # 敌人状态还原
            #     self.attack_target.state = Fighter.ENUM_IDLE
            # # 触发移动事件
            # if move_frame is not None:
            #     if frame == move_frame[0][0]:
            #         # 向敌人移动
            #         total_frame = move_frame[0][1] - move_frame[0][0] + 1
            #         self.start_move(self.attack_target.x + 50, self.attack_target.y, total_frame * frame_count)
            #     if frame == move_frame[1][0]:
            #         # 回到自己的位置
            #         total_frame = move_frame[1][1] - move_frame[1][0] + 1
            #         self.start_move(self.raw_x, self.raw_y, total_frame * frame_count)

        return cb

    def move_cb(self, move_frame):
        def cb(frame):
            # if frame == move_frame[1]:
            #     self.state = self.ENUM_IDLE
            pass

        return cb

    def set_xy(self, x, y):
        self.x = x
        self.y = y
        self.ani_idle.x = x
        self.ani_idle.y = y
        self.ani_attack.x = x
        self.ani_attack.y = y
        self.ani_be_attacked.x = x
        self.ani_be_attacked.y = y
        if self.ani_move:
            self.ani_move.x = x
            self.ani_move.y = y

    def logic(self):
        self.move()
        if self.state == Fighter.ENUM_IDLE:
            self.ani_idle.update()
        elif self.state == Fighter.ENUM_ATK:
            self.ani_attack.update()
        elif self.state == Fighter.ENUM_BE_ATK:
            offset_x = random.randint(1, 7)
            if self.is_enemy:
                offset_x *= -1
            self.ani_be_attacked.x = self.x + offset_x
            self.ani_be_attacked.update()
        elif self.state == Fighter.ENUM_MOVE:
            if self.ani_move:
                self.ani_move.update()

    def render(self, target):
        if self.state == Fighter.ENUM_IDLE:
            self.ani_idle.draw(target)
        elif self.state == Fighter.ENUM_ATK:
            self.ani_attack.draw(target)
        elif self.state == Fighter.ENUM_BE_ATK:
            self.ani_be_attacked.draw(target)
        elif self.state == Fighter.ENUM_MOVE:
            if self.ani_move:
                self.ani_move.draw(target)

        self.render_hp_mp(target)

    def start_move(self, x, y):
        """
        设置终点，开启位移
        frame_amount是主循环次数，不是动画帧数，动画帧*动画frame_amount才等于frame_amount
        x,y是终点
        """
        total_frame = self.move_frame[0][1] - self.move_frame[0][0] + 1
        frame_amount = total_frame * self.ani_attack_frame_count
        self.x0 = self.x
        self.y0 = self.y
        self.xt = x
        self.yt = y
        # length = math.sqrt((self.xt - self.x) ** 2 - (self.yt - self.y) ** 2)
        self.n = 0
        self.k = 1 / frame_amount
        self.moving = True
        self.state = Fighter.ENUM_MOVE
        # if self.ani_move:
        #     self.ani_move.reset()

    def move(self):
        """
        实时计算当前坐标
        """
        if not self.moving:
            return
        self.n += self.k
        if self.n >= 1:
            self.n = 1
            self.moving = False
            self.state = Fighter.ENUM_IDLE
        self.x = self.n * (self.xt - self.x0) + self.x0
        self.y = self.n * (self.yt - self.y0) + self.y0
        self.set_xy(self.x, self.y)

    def render_hp_mp(self, target):
        """
        绘制生命值和魔法值
        """
        Sprite.draw_text(target, self.x, self.y, f"{self.hp[0]}/{self.hp[1]}", g.fnt_talk, (255, 0, 0))
        Sprite.draw_text(target, self.x, self.y + 20, f"{self.mp[0]}/{self.mp[1]}", g.fnt_talk, (0, 0, 255))

    def mouse_move(self, x, y):
        """
        鼠标移动事件
        """
        if self.state != self.ENUM_IDLE:
            return False
        # 只有人物处于idle状态才能高亮,鼠标是否点中
        dx, dy = int(x - (self.x - self.ani_idle.dw / 2)), int(y - (self.y - self.ani_idle.dh / 2))
        return self.ani_idle.collide(dx, dy)


class FightMenu:
    """
    战斗操作菜单
    """

    def __init__(self, x, y):
        self.img_ani_menu = pygame.image.load("./resource/PicLib/all_sys/fight_menu_new.png").convert_alpha()
        self.ani_menu = Animation(x, y, self.img_ani_menu, 142, 143, 600, False, [0, 8], fps=g.fps)
        self.state = 0
        self.visible = True
        self.x = x
        self.y = y
        btn_fnt = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui', 16, bold=True)

        # 7,28
        img_left_normal = pygame.image.load("./resource/PicLib/all_sys/fight_menu_left_1.png").convert_alpha()
        img_left_move = pygame.image.load("./resource/PicLib/all_sys/fight_menu_left_3.png").convert_alpha()
        img_left_down = pygame.image.load("./resource/PicLib/all_sys/fight_menu_left_2.png").convert_alpha()
        self.btn_left = ButtonEx(self.x + 7, self.y + 28, "仙术", btn_fnt, img_left_normal, img_left_move, img_left_down,
                                 cb=self.reset, rgb=(255, 255, 255), rgb2=(0, 0, 255))

        # 95,28
        img_right_normal = pygame.image.load("./resource/PicLib/all_sys/fight_menu_right_1.png").convert_alpha()
        img_right_move = pygame.image.load("./resource/PicLib/all_sys/fight_menu_right_3.png").convert_alpha()
        img_right_down = pygame.image.load("./resource/PicLib/all_sys/fight_menu_right_2.png").convert_alpha()
        self.btn_right = ButtonEx(self.x + 95, self.y + 28, "道具", btn_fnt, img_right_normal, img_right_move,
                                  img_right_down, cb=self.reset, rgb=(255, 255, 255), rgb2=(0, 0, 255))

        # 27,7
        img_up_normal = pygame.image.load("./resource/PicLib/all_sys/fight_menu_up_1.png").convert_alpha()
        img_up_move = pygame.image.load("./resource/PicLib/all_sys/fight_menu_up_3.png").convert_alpha()
        img_up_down = pygame.image.load("./resource/PicLib/all_sys/fight_menu_up_2.png").convert_alpha()
        self.btn_up = ButtonEx(self.x + 27, self.y + 7, "待定", btn_fnt, img_up_normal, img_up_move, img_up_down,
                               cb=self.reset, rgb=(255, 255, 255), rgb2=(0, 0, 255))

        # 27,96
        img_down_normal = pygame.image.load("./resource/PicLib/all_sys/fight_menu_down_1.png").convert_alpha()
        img_down_move = pygame.image.load("./resource/PicLib/all_sys/fight_menu_down_3.png").convert_alpha()
        img_down_down = pygame.image.load("./resource/PicLib/all_sys/fight_menu_down_2.png").convert_alpha()
        self.btn_down = ButtonEx(self.x + 27, self.y + 96, "待定", btn_fnt, img_down_normal, img_down_move, img_down_down,
                                 cb=self.reset, rgb=(255, 255, 255), rgb2=(0, 0, 255))

        # 49,49
        img_mid_normal = pygame.image.load("./resource/PicLib/all_sys/fight_menu_mid_1.png").convert_alpha()
        img_mid_move = pygame.image.load("./resource/PicLib/all_sys/fight_menu_mid_3.png").convert_alpha()
        img_mid_down = pygame.image.load("./resource/PicLib/all_sys/fight_menu_mid_2.png").convert_alpha()
        self.btn_mid = ButtonEx(self.x + 49, self.y + 49, "攻击", btn_fnt, img_mid_normal, img_mid_move, img_mid_down,
                                cb=self.reset, rgb=(255, 255, 255), rgb2=(0, 0, 255))

    def logic(self):
        if not self.visible:
            return
        self.ani_menu.update()
        if self.ani_menu.least_once:
            self.ani_menu.pause = True

    def render(self, target):
        if not self.visible:
            return
        self.ani_menu.draw_src(target, self.x, self.y)
        if self.ani_menu.pause:
            self.btn_left.draw(target)
            self.btn_right.draw(target)
            self.btn_up.draw(target)
            self.btn_down.draw(target)
            self.btn_mid.draw(target)

    def mouse_down(self, x, y, pressed):
        if not self.visible:
            return
        if self.ani_menu.pause:
            self.btn_left.mouse_down(x, y)
            self.btn_right.mouse_down(x, y)
            self.btn_up.mouse_down(x, y)
            self.btn_down.mouse_down(x, y)
            self.btn_mid.mouse_down(x, y)

    def mouse_move(self, x, y):
        if not self.visible:
            return
        if self.ani_menu.pause:
            self.btn_left.mouse_move(x, y)
            self.btn_right.mouse_move(x, y)
            self.btn_up.mouse_move(x, y)
            self.btn_down.mouse_move(x, y)
            self.btn_mid.mouse_move(x, y)

    def mouse_up(self):
        if not self.visible:
            return
        if self.ani_menu.pause:
            self.btn_left.mouse_up()
            self.btn_right.mouse_up()
            self.btn_up.mouse_up()
            self.btn_down.mouse_up()
            self.btn_mid.mouse_up()

    def reset(self):
        self.ani_menu.reset()


class FightManager:
    """
    战斗管理器
    """
    # 友军位置
    TEAMMATE_POSITION = [
        [355, 342],
        [452, 288],
        [376, 427],
        [470, 388],
        [575, 324]
    ]
    # 敌人位置
    ENEMY_POSITION = [
        [295, 207],
        [198, 262],
        [274, 133],
        [183, 180],
        [83, 226]
    ]

    def __init__(self):
        """
        初始化战斗管理器
        """
        # 敌人列表
        self.enemy_list = []
        # 我方列表
        self.teammate_list = []
        # 两者列表
        self.fighter_list = []
        # 回合数
        self.round = 1
        # 是否打开战斗系统
        self.switch = False
        # 战斗背景地图
        self.img_bg = None
        # 战斗菜单动画
        self.fight_menu = FightMenu(0, 480 - 143)
        # 战斗播放器
        self.battle_player = BattlePlayer()
        # 阴影

    def start(self, teammate_list: List[FighterRenderer], enemy_list: List[FighterRenderer], map_id):
        """
        开始战斗
        """
        self.teammate_list = teammate_list
        self.enemy_list = enemy_list
        self.fighter_list = self.teammate_list + self.enemy_list
        self.img_bg = pygame.image.load(f"./resource/PicLib/all_fight/{map_id}.jpg")
        self.switch = True
        # 初始化人物位置
        for fighter in self.fighter_list:
            fighter.fight_mgr = self
            if fighter.is_enemy:
                x, y = self.ENEMY_POSITION[fighter.position]
            else:
                x, y = self.TEAMMATE_POSITION[fighter.position]
            fighter.raw_x = x
            fighter.raw_y = y
            fighter.set_xy(x, y)
        t1 = self.teammate_list[0]
        t2 = self.teammate_list[1]
        t3 = self.teammate_list[2]
        t4 = self.teammate_list[3]
        t5 = self.teammate_list[4]

        e1 = self.enemy_list[0]
        e2 = self.enemy_list[1]
        e3 = self.enemy_list[2]
        e4 = self.enemy_list[3]
        e5 = self.enemy_list[4]

        # # TODO:测试战斗播放器
        # action1 = Action(action_type="MOVE", fighter=t1, action_args=[0, 0])
        # action2 = Action(action_type="MOVE", fighter=t1, action_args=[200, 200])
        # action3 = Action(action_type="MOVE", fighter=t1, action_args=[0, 0])
        # action4 = Action(action_type="MOVE", fighter=t1, action_args=[200, 200])
        # action5 = Action(action_type="MOVE", fighter=t1, action_args=[0, 0])
        # action6 = Action(action_type="MOVE", fighter=t1, action_args=[200, 200])
        # action7 = Action(action_type="MOVE", fighter=t1, action_args=[0, 0])
        #
        # action_list = [action1, action2, action3, action4, action5, action6, action7]
        # self.battle_player.play(action_list)

    def debug_start(self):
        """
        debug战斗系统
        """
        self.img_bg = pygame.image.load(f"./resource/PicLib/all_fight/{2}.jpg")
        self.switch = True
        xys_res = g.fighter_res_mgr.load("逍遥生-扇")
        jmw_res = g.fighter_res_mgr.load("巨魔王-刀")
        jmw160_res = g.fighter_res_mgr.load("巨魔王-刀160")

        hmr_res = g.fighter_res_mgr.load("狐美人-爪")
        stb_res = g.fighter_res_mgr.load("神天兵-枪")
        wtj_res = g.fighter_res_mgr.load("舞天姬-飘带")

        jjxxg_res = g.fighter_res_mgr.load("进阶吸血鬼")
        jjfh_res = g.fighter_res_mgr.load("进阶凤凰")
        jjgdrs_res = g.fighter_res_mgr.load("进阶古代瑞兽")
        yz_res = g.fighter_res_mgr.load("野猪")
        hmc_res = g.fighter_res_mgr.load("海毛虫")

        xys_renderer = FighterRenderer(*self.TEAMMATE_POSITION[0], is_actor=True, res_list=[xys_res])
        jmw_renderer = FighterRenderer(*self.TEAMMATE_POSITION[1], is_actor=True, res_list=[jmw_res, jmw160_res])
        hmr_renderer = FighterRenderer(*self.TEAMMATE_POSITION[2], is_actor=True, res_list=[hmr_res])
        stb_renderer = FighterRenderer(*self.TEAMMATE_POSITION[3], is_actor=True, res_list=[stb_res])
        wtj_renderer = FighterRenderer(*self.TEAMMATE_POSITION[4], is_actor=True, res_list=[wtj_res])

        jjxxg_renderer = FighterRenderer(*self.ENEMY_POSITION[0], is_actor=False, res_list=[jjxxg_res])
        jjfh_renderer = FighterRenderer(*self.ENEMY_POSITION[1], is_actor=False, res_list=[jjfh_res])
        jjgdrs_renderer = FighterRenderer(*self.ENEMY_POSITION[2], is_actor=False, res_list=[jjgdrs_res])
        yz_renderer = FighterRenderer(*self.ENEMY_POSITION[3], is_actor=False, res_list=[yz_res])
        hmc_renderer = FighterRenderer(*self.ENEMY_POSITION[4], is_actor=False, res_list=[hmc_res])

        self.teammate_list.append(xys_renderer)
        self.teammate_list.append(jmw_renderer)
        self.teammate_list.append(hmr_renderer)
        self.teammate_list.append(stb_renderer)
        self.teammate_list.append(wtj_renderer)

        self.enemy_list.append(jjxxg_renderer)
        self.enemy_list.append(jjfh_renderer)
        self.enemy_list.append(jjgdrs_renderer)
        self.enemy_list.append(yz_renderer)
        self.enemy_list.append(hmc_renderer)

        self.fighter_list = self.teammate_list + self.enemy_list

        # # TODO:测试战斗播放器
        action1 = Action(action_type="MOVE", fighter=jmw_renderer, action_args=[332, 216])
        action2 = Action(action_type="ATK", fighter=jmw_renderer)
        action3 = Action(action_type="ATK", fighter=jmw_renderer)
        action4 = Action(action_type="ATK", fighter=jmw_renderer)
        action5 = Action(action_type="ATK", fighter=jmw_renderer)
        action6 = Action(action_type="ATK", fighter=jmw_renderer)
        action7 = Action(action_type="MOVE", fighter=jmw_renderer, action_args=[100, 100])
        action8 = Action(action_type="MOVE", fighter=jmw_renderer, action_args=[200, 200])
        action9 = Action(action_type="MOVE", fighter=jmw_renderer, action_args=[100, 100])

        action_list = [action1, action2, action3, action4, action5, action6, action7, action8, action9]
        self.battle_player.play(action_list)

    def logic(self):
        self.fight_menu.logic()
        self.battle_player.logic()
        for fighter in self.fighter_list:
            fighter.logic()
        self.fighter_list.sort(key=lambda obj: obj.y)

    def render(self, surface):
        if not self.switch:
            return
        # 画背景
        Sprite.blit(surface, self.img_bg, 0, 0)
        # 画战斗者
        for fighter in self.fighter_list:
            fighter.render(surface)
        self.fight_menu.render(surface)

    def mouse_down(self, x, y, pressed):
        self.fight_menu.mouse_down(x, y, pressed)
        print(x, y)

    def mouse_move(self, x, y):
        self.fight_menu.mouse_move(x, y)
        # focus = None
        # for fighter in self.fighter_list[::-1]:
        #     if fighter.mouse_move(x, y):
        #         fighter.ani_idle.sw_light = True
        #         focus = fighter
        #         break
        # for fighter in self.fighter_list:
        #     if fighter != focus:
        #         fighter.ani_idle.sw_light = False
        # if not focus:
        #     return False
        #
        # return True
        pass

    def mouse_up(self, x, y, pressed):
        self.fight_menu.mouse_up()


class Action:
    """
    战斗播放器所需的action
    """

    def __init__(
            self,
            action_type: str,
            fighter: FighterRenderer = None,
            action_args: list = None,
            animation: Animation = None
    ):
        """
        action_type:MAGIC 人物施法,MOVE 人物位移,ATK 人物攻击,BE_ATK 人物被攻击,MISS 人物闪避,
        """
        self.action_type = action_type
        self.fighter = fighter
        self.action_args = action_args
        self.animation = animation
        self.done: bool = False  # 是否完成

    def start(self):
        """
        开始执行
        """
        if self.action_type == "MOVE":
            self.fighter.move(*self.action_args)
        elif self.action_type == "ATK":
            self.fighter.attack()

    def logic(self):
        if self.action_type == "MOVE":
            if self.fighter.state != self.fighter.ENUM_MOVING:
                self.done = True
        elif self.action_type == "ATK":
            if self.fighter.state != self.fighter.ENUM_ATK:
                self.done = True


class BattlePlayer:
    """
    战斗播放器
    """

    def __init__(self):
        # 播放器是否正在运行
        self.is_running: bool = False
        # 动作列表
        self.action_list: List[Action] = []
        # 当前动作
        self.current_action: Action = None

    def logic(self):
        """
        战斗播放器逻辑
        """
        if not self.is_running:
            return

        self.current_action.logic()

        # 如果当前action已结束，那就弹出下一个action
        if self.current_action.done:
            if len(self.action_list) == 0:
                self.is_running = False
                return
            self.current_action = self.action_list.pop(0)
            self.current_action.start()

    def play(self, action_list: List[Action]):
        """
        播放动画
        """
        if len(action_list) == 0:
            return
        self.action_list = action_list
        self.current_action = action_list.pop(0)
        self.current_action.start()
        self.is_running = True
